昨天我們學了 API 中的標頭和快取運作原理。今天,我們要動手練習 POST 請求。
POST 請求是與 API 互動時很常見的一種操作,也是比較容易發生錯誤的地方。為了讓練習更安全、更簡單,我是用一個叫做 httpbin.org
的網站,這個網站是專門為開發者設計的測試環境。
使用 httpbin.org
,我們可以把資料送出去,然後它會完整地回傳剛剛我們送出的資訊,讓我們清楚看到資料到底怎麼傳送的,方便理解和除錯。這樣我們就能更放心地練習 POST 請求,學會正確的用法。
我今天的小專案目標是用 Python 的 requests 套件,向 httpbin.org 送出一個 POST 請求,把資料放在請求的正文(body)裡。我會傳送一份 JSON 格式的資料給伺服器,也會比較 JSON 和表單(form)兩種格式的差別,並加上自訂的標頭(headers)來模擬真實的 API,最後學習如何觀察回傳結果並處理錯誤。
在 HTTP 裡,有幾種常見的方法用來和伺服器溝通,像是 GET、POST、PUT、DELETE。
POST 方法是用來把資料送給伺服器的。
舉例來說:
送我們的帳號和密碼到網站做登入。
把 JSON 格式的資料傳給 API 伺服器,讓它做分析或處理。
上傳表單資料或檔案給伺服器。
POST 最特別的是,它會把資料放在請求的正文(body)裡面傳送,不像 GET 那樣把資料放在網址上,這樣更安全也可以傳送比較多、更複雜的資料。
步驟 0:環境準備
pip install requests
步驟 1:練習一個 POST 的範例
建立一個叫 day23_post_httpbin.py
的檔案。
import requests, json
URL = "https://httpbin.org/post"
payload = {
"user": "ariel",
"task": "post-demo",
"tags": ["http", "post", "json"]
}
r = requests.post(URL, json=payload, timeout=10)
r.raise_for_status()
data = r.json()
print("HTTP 狀態碼:", r.status_code)
print("伺服器看到的 Content-Type:", data["headers"]["Content-Type"])
print("伺服器回顯的 JSON:", json.dumps(data["json"], ensure_ascii=False))
步驟 2:比較 JSON 和表單格式
定義兩個函式,一個用 JSON 傳資料,另一個用表單傳資料。
def post_json():
return requests.post(URL, json={"msg": "hello-json"}, timeout=10).json()
def post_form():
return requests.post(URL, data={"msg": "hello-form"}, timeout=10).json()
print("—— JSON 版 ——")
j = post_json()
print("Content-Type:", j["headers"]["Content-Type"])
print("json 回顯 :", j["json"])
print("form 回顯 :", j["form"])
print("\n—— 表單版 ——")
f = post_form()
print("Content-Type:", f["headers"]["Content-Type"])
print("json 回顯 :", f["json"])
print("form 回顯 :", f["form"])
比較結果:
用 JSON 傳的資料會出現在回應的 json
部分。
用表單傳的資料會出現在回應的 form
部分。
Content-Type 標頭也不同,JSON 是 application/json
,表單是 application/x-www-form-urlencoded
。
步驟 3:加上自訂標頭
我們可以自己定義標頭,例如加入授權的 Token。
headers = {
"X-Demo": "day23",
"Authorization": "Bearer FAKE_TOKEN_FOR_DEMO"
}
r = requests.post(URL, json={"demo": True}, headers=headers)
data = r.json()
print("伺服器看到的 Authorization:", data["headers"].get("Authorization"))
print("伺服器看到的 X-Demo :", data["headers"].get("X-Demo"))
這樣能模擬真實情況下,API 需要帶 Token 或金鑰的請求。
步驟 4:練習錯誤處理
網路請求有時會失敗,比如伺服器回錯誤或網路斷線。我們可以加錯誤處理,讓程式不會直接當掉。
try:
r = requests.post("https://httpbin.org/status/404", json={"x":1}, timeout=5)
r.raise_for_status()
except requests.exceptions.HTTPError as e:
print("HTTP 錯誤:", e)
except requests.exceptions.Timeout:
print("連線逾時,請檢查網路。")
except requests.exceptions.RequestException as e:
print("其他錯誤:", e)
這段程式能捕捉不同錯誤,像是 HTTP 錯誤、連線逾時等,幫助我們知道問題出在哪裡並且安全處理。
執行結果:
HTTP 狀態碼: 200
伺服器看到的 Content-Type: application/json
伺服器回顯的 JSON: {"tags": ["http", "post", "json"], "task": "post-demo", "user": "alice"}
—— JSON 版 ——
Content-Type: application/json
json 回顯 : {'msg': 'hello-json'}
form 回顯 : {}
—— 表單版 ——
Content-Type: application/x-www-form-urlencoded
json 回顯 : None
form 回顯 : {'msg': 'hello-form'}
伺服器看到的 Authorization: Bearer FAKE_TOKEN_FOR_DEMO
伺服器看到的 X-Demo : day23
HTTP 錯誤: 404 Client Error: NOT FOUND for url: https://httpbin.org/status/404
接下來,我會簡單的解釋執行結果的內容。
HTTP 狀態碼:200
這是表示主要 POST 請求成功(OK)。代表伺服器接受並處理了我們的請求。
伺服器看到的 Content-Type:application/json
我們用的是 JSON 請求體。requests.post(..., json=payload)
會自動加上這個標頭並把資料序列化成 JSON。
伺服器回顯的 JSON:{"tags": [...], "task": "post-demo", "user": "alice"}
伺服器把我們送去的 JSON 原封不動回傳。證明 payload 有正確送達與被解析。
—— JSON 版 ——
Content-Type: application/json
這是確認 JSON 送法無誤。
json 回顯 : {'msg': 'hello-json'}
JSON 主體被伺服器解析成 JSON。
form 回顯 : {}
因為不是用表單送,所以伺服器的 form
區是空的。
—— 表單版 ——
Content-Type: application/x-www-form-urlencoded
這段是用 data=...
(表單)送,Content-Type 就會是表單類型。
json 回顯 : None
不是 JSON body,所以解析不到 JSON。
form 回顯 : {'msg': 'hello-form'}
表單欄位成功被伺服器解析並回顯。
HTTP 錯誤:404 ... /status/404
這是刻意打的 404 測試端點,用來驗證錯誤處理。r.raise_for_status()
正常丟出 HTTPError,代表例外處理有生效,這不是我們的程式壞掉。
今天我學會了如何用 Python 送出 POST 請求,了解 POST 是把資料放在請求的正文裡,不像 GET 是放在網址後面。我也知道了 JSON 和表單格式的差別,主要是在 Content-Type 標頭和資料格式上。透過使用 httpbin.org
,我可以安全地測試標頭、正文和身份驗證,並觀察伺服器如何接收資料。這次練習讓我更清楚 API 互動的流程,也學會在發送資料前檢查格式和處理錯誤。